% The code below is neccessary for the framework to modify these sentences.

:- dynamic actualSituation/1,perception/5,executedAction/2,position/3,
orientacion/2,llave/4,puerta/4.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             Reglas diagnosticas                                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
llave(X,Y,S) :- perception([llave,_,_],_,_,_,_),actualSituation(S),position(X,Y,S).              %% CONTROLAR EN TODO EL DOCUMENTO EL TEMA DE LLAVE, PORQUE LO HABIAMOS IMPLEMETNADO CON EL NUMERO DE LLAVE PRIMERO
salida(A,L,X,Y,S) :- perception([_,salida,_],_,_,_,_),actualSituation(S),position(X,Y,S).
salida(A,L,X,Y,S) :- perception([_,salida,cerrada],_,_,_,_),actualSituation(S),position(X,Y,S).
pared(X,Y,1,S) :- perception([_,_,_],pared,_,_,_),actualSituation(S),position(X,Y,S).
pared(X,Y,2,S) :- perception([_,_,_],_,pared,_,_),actualSituation(S),position(X,Y,S).
pared(X,Y,3,S) :- perception([_,_,_],_,_,pared,_),actualSituation(S),position(X,Y,S).
pared(X,Y,4,S) :- perception([_,_,_],_,_,_,pared),actualSituation(S),position(X,Y,S).

%perception([_,_,X,Y,_],S) :- position(X,Y,S).
%perception([_,_,_,_,1],S) :- orientacion(1,S).
%perception([_,_,_,_,2],S) :- orientacion(2,S).
%perception([_,_,_,_,3],S) :- orientacion(3,S).
%perception([_,_,_,_,4],S) :- orientacion(4,S).
%perception([1,_,X,Y,_],S) :- llave(1,X,Y,S).
%perception([_,1,X,Y,_],S) :- puerta(1,X,Y,S).
%perception([_,2,X,Y,_],S) :- puerta(2,X,Y,S).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             Reglas Causales                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             Axiomas de estado Sucesor                              %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%Si la posicion del agente cambia
est(S1) :- S1 > 0,S is S1-1,executedAction(Avanzar,S),position(X,Y,S),suma(Y,-1,Y1),orientacion(1,S),not(pared(X,Y,1,S)),asserta(position(X,Y,S1)).
est(S1) :- S1 > 0,S is S1-1,executedAction(Avanzar,S),position(X,Y,S),suma(Y,1,Y1),orientacion(2,S),not(pared(X,Y,2,S)),asserta(position(X,Y1,S1)).
est(S1) :- S1 > 0,S is S1-1,executedAction(Avanzar,S),position(X,Y,S),suma(X,1,X1),orientacion(3,S),noy(pared(X,Y,3,S)),asserta(position(X1,Y,S1)).
est(S1) :- S1 > 0,S is S1-1,executedAction(Avanzar,S),position(X,Y,S),suma(X,-1,X1),orientacion(4,S),not(pared(X,Y,4,S)),asserta(position(X1,Y,S1)).

%Si la posicion del NO agente cambia
est(S1) :- S1 > 0,S is S1-1,executedAction(A,S),A\=Avanzar,position(X,X,S),asserta(position(X,Y,S1)).

%Cambia la orientacion del agente
est(S1) :- S1 > 0,S is S1-1,executedAction(GirarDer,S),orientacion(O,S),gireDer(O,O1),asserta(orientacion(O1,S1)).
est(S1) :- S1 > 0,S is S1-1,executedAction(GirarIzq,S),orientacion(O,S),gireIzq(O,O1),asserta(orientacion(O1,S1)).

%Si la orientacion no cambia
est(S1) :- S1 > 0,S is S1-1,executedAction(A,S),A\=GirarDer,A\=GirarIzq,orientacion(O,S),asserta(orientacion(O,S1)).

%si levanta llave
est(S1) :- S1 > 0,S is S1-1,executedAction(LevantarLlave,S),position(X,Y,S),llave(X,Y,S),asserta(tieneLlave(1,S1)).

%si no levanta llave
est(S1) :- S1 > 0,S is S1-1,executedAction(A,S),A\=LevantarLlave,tieneLlave(L,S),asserta(tieneLlave(L,S1)).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             Actions Evaluations                                 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%levantar llave es excelente.
%% ESTA NO IRIA SI USAMOS EL "noAction" excelent(salir,S) :- position(X,Y,S),orientacion(3,S),tieneLlave(L,S),asserta(puerta(L,X,Y)).
excelent(levantarLlave,S) :- position(X,Y,S),llave(1,X,Y,S),tieneLlave(0,S).

% avanzar al este es muy bueno
very_good(Avanzar,S) :- position(X,Y,S),orientacion(3,S),not(pared(X,Y,3,S)).


%Avanzar en las otras direcciones es bueno
good(Avanzar,S) :- position(X,Y,S),orientacion(2,S),not(pared(X,Y,2,S)).
good(Avanzar,S) :- position(X,Y,S),orientacion(1,S),not(pared(X,Y,1,S)).
good(Avanzar,S) :- position(X,Y,S),orientacion(4,S),not(pared(X,Y,4,S)).


% Si todo lo demas no se puede, gira a la derecha o izquierda   %% ACA NO SE QUE PRECONDICION TIENE QUE TENER, CALCULO QUE NINGUNA
regular(GirarDer,S) :- position(X,Y,S).
regular(GirarIzq,S) :- position(X,Y,S).


bestAction(noAction,S) :- goalReached(S),!.
bestAction(X,S) :- excelent(X,S),!.
bestAction(X,S) :- very_good(X,S),!.
bestAction(X,S) :- good(X,S),!.
bestAction(X,S) :- regular(X,S),!.




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                             Extra sentences                                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

maxCell(S) :- S is 3.

%pared(X,Y,1) :- celda(X,Y,A,B,C,D),asserta(A,0).
%pared(X,Y,2) :- celda(X,Y,A,B,C,D),asserta(B,0).
%pared(X,Y,3) :- celda(X,Y,A,B,C,D),asserta(C,0).
%pared(X,Y,4) :- celda(X,Y,A,B,C,D),asserta(D,0).

add(P,X,P1) :- P1 is P+X.

suma(P,O,P1) :- P<maxCell(Mx),P<Mx,add(P,O,P1);

gireDer(1,3).
gireDer(2,4).
gireDer(3,2).
gireDer(4,1).

gireIzq(1,4).
gireIzq(2,3).
gireIzq(3,1).
gireIzq(4,2).

goalReached(S) :- salida(A,L,X,Y,S),position(X,Y,S),tieneLlave(L,S),orientacion(3,S).